import { History, ModifyObjectState, EventType as HistoryEventType, EventData as HistoryEventData } from "./history";
import * as mvc from "./mvc";
/**
 * 默认历史记录实例。
 */
export let history: History = History.create(History);
export function setHistory(value: History): void {
    if (!history) {
        mvc.context.addEventListener(
            HistoryEventType[HistoryEventType.HistoryState],
            (event) => {
                const historyEventData: HistoryEventData<mvc.Notification> = event.data;
                const historyData = historyEventData.data;
                mvc.context.sendNotification(historyData.type, historyData.data, historyData.target);
            },
            null
        );
    }

    history = value;
    history.dispatcher = mvc.context;
}
/**
 * 将目标属性修改为 getter setter。
 */
export function getterSetter(
    getter: boolean,
    setter: boolean
) {
    return function (target: any, key: string): void {
        if (!getter && !setter) {
            return;
        }

        const privateKey = "_" + key; // 私有 key。TODO 不可枚举
        const attributes = Object.getOwnPropertyDescriptor(target, key) || {};
        attributes.configurable = true;

        if (getter && !attributes.get) {
            attributes.get = function (this: any): any {
                return this[privateKey];
            };
        }

        if (setter) {
            const prevSetter = attributes.set;
            if (prevSetter) {
                attributes.set = function (value: any) {
                    prevSetter(value);
                };
            }
            else {
                attributes.set = function (this: any, value: any) {
                    this[privateKey] = value;
                };
            }
        }
        else {
            attributes.set = function (this: any, value: any) {
                this[privateKey] = value;
                delete attributes.set;
                Object.defineProperty(this, key, attributes);
            };
        }

        Object.defineProperty(target, key, attributes);
    };
}
/**
 * 生成历史状态或发出通知。
 */
export function addHistoryAndNotification(addHistory: boolean, notificationType: number = 0) {
    return function (target: any, key: string): void {
        if (!addHistory && !notificationType) {
            return;
        }

        const privateKey = "_" + key; // 私有 key。TODO 不可枚举
        const attributes: PropertyDescriptor = {};
        attributes.configurable = true;
        attributes.set = function (this: any, value: any) {
            if (privateKey in this) {
                const prevValue = this[privateKey];
                if (addHistory) {
                    const state = ModifyObjectState.createState(this, privateKey, value); // 生成历史状态，使用私有 key。
                    if (state) {
                        if (notificationType) { // 通知由历史状态携带。
                            const data: mvc.Notification = { type: notificationType, target: this, data: prevValue };
                            state.data = data;
                        }

                        history.add(state);
                    }
                }
                else {
                    this[privateKey] = value;
                    if (notificationType) { // 发出通知。
                        mvc.context.sendNotification(notificationType, prevValue, this);
                    }
                }
            }
            else {
                this[privateKey] = value;
            }
        };

        Object.defineProperty(target, key, attributes);
    };
}